/**
 * @description WebSocket 客户端类
 * @param {string} url WebSocket 服务器地址
 * @param {string[]} protocols WebSocket 协议
 * @param {number} maxReconnectAttempts 最大重连次数
 * @param {number} reconnectInterval 重连间隔时间（毫秒）
 */
class Socket {
	constructor(url, protocols = [], maxReconnectAttempts = 5, reconnectInterval = 3000) {
		this.url = url;
		this.protocols = protocols;
		this.socketTask = null;
		this.listeners = {
			open: [],
			message: [],
			close: [],
			error: []
		};
		//消息队列
		this.messageQueue = [];
		this.reconnectAttempts = 0;
		this.maxReconnectAttempts = maxReconnectAttempts;
		this.reconnectInterval = reconnectInterval;
		this.reconnectTimeout = null;
	}

	// 连接 WebSocket
	async connect() {
		if (this.socketTask) {
			console.warn('WebSocket is already connected.');
			return;
		}

		this.socketTask = await uni.connectSocket({
			url: this.url,
			protocols: this.protocols,
			complete: (e) => {
				console.log("socket :", e);
			},
			success: (e) => {
				console.log("success :", e);
			},
			fail: (e) => {
				console.log("fail :", e);
			}
		});
		this.socketTask.onOpen(this.handleOpen.bind(this));
		this.socketTask.onMessage(this.handleMessage.bind(this));
		this.socketTask.onClose(this.handleClose.bind(this));
		this.socketTask.onError(this.handleError.bind(this));
	}

	// 处理连接打开事件
	handleOpen(event) {
		console.log('WebSocket connection opened:', event);
		if (this.socketTask && this.socketTask.readyState === this.socketTask.OPEN) {
			this.messageQueue.forEach(item=> this.send(item));
			this.messageQueue = [];
		}
		this.emit('open', event);
		this.resetReconnectAttempts();
	}

	// 处理消息事件
	handleMessage(event) {
		console.log('WebSocket message received:', event);
		this.emit('message', event);
	}

	// 处理关闭事件
	handleClose(event) {
		console.log('WebSocket connection closed:', event);
		this.emit('close', event);
		this.socketTask = null; // 清除 socket 实例
		this.reconnect();
	}

	// 处理错误事件
	handleError(event) {
		console.error('WebSocket error:', event);
		this.emit('error', event);
	}

	// 发送消息
	send(data) {
		if (!this.isSocketConnected()) {
			this.messageQueue.push(data)
			console.error('添加消息队列等待执行 WebSocket is not connected.');
			return;
		}

		this.socketTask.send({
			data: JSON.stringify(data),
			success: (res) => {
				console.log('Message sent:', res);
			},
			fail: (err) => {
				console.error('Failed to send message:', err);
			}
		});
	}
	
	isSocketConnected() {
		console.log(this.socketTask)
	    return this.socketTask && ((this.socketTask?._webSocket?.readyState || this.socketTask.readyState) === this.socketTask.OPEN);
	}

	// 关闭 WebSocket 连接
	close(code = 1000, reason = '') {
		if (!this.socketTask) {
			console.warn('WebSocket is not connected.');
			return;
		}
	
		this.socketTask.close({
			code: code,
			reason: reason,
			success: () => {
				console.log('WebSocket connection closed successfully.');
			},
			fail: (err) => {
				console.error('Failed to close WebSocket connection:', err);
			}
		});
	}

	// 添加事件监听器
	on(event, callback) {
		if (!this.listeners[event]) {
			this.listeners[event] = [];
		}
		this.listeners[event].push(callback);
	}

	// 移除事件监听器
	off(event, callback) {
		if (this.listeners[event]) {
			this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
		}
	}

	// 触发事件
	emit(event, data) {
		if (this.listeners[event]) {
			this.listeners[event].forEach(callback => callback(data));
		}
	}

	// 重置重连尝试次数
	resetReconnectAttempts() {
		this.reconnectAttempts = 0;
	}

	// 重连机制
	reconnect() {
		console.log('连接关闭，开始重连')
		if (this.reconnectAttempts >= this.maxReconnectAttempts) {
			console.error('Max reconnect attempts reached. Giving up.');
			this.emit('maxReconnectAttemptsReached');
			return;
		}

		console.log(`Reconnecting... Attempt ${this.reconnectAttempts + 1}`);
		this.reconnectAttempts++;

		this.reconnectTimeout = setTimeout(() => {
			this.connect();
		}, this.reconnectInterval);
	}

	// 清除重连定时器
	clearReconnectTimeout() {
		if (this.reconnectTimeout) {
			clearTimeout(this.reconnectTimeout);
			this.reconnectTimeout = null;
		}
	}
}

export default Socket;